package com.tbynet.jwp.framework.kit;

import com.jfinal.kit.StrKit;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Map;
import java.util.Random;

/**
 * 字符串处理工具类
 *
 * @author 佰亿互联
 * @version 3.1
 * @since 2025-11-04
 */
public class StringKit {

    // ========== 字符串验证方法 ==========

    /**
     * 检查字符串是否为整数
     *
     * @param str 输入字符串
     * @return 是否为整数
     *
     * @example
     * <pre>{@code
     * boolean result = StringKit.isInteger("123"); // true
     * boolean result2 = StringKit.isInteger("12.3"); // false
     * }</pre>
     */
    public static boolean isInteger(String str) {
        if (StrKit.isBlank(str)) {
            return false;
        }

        try {
            Integer.parseInt(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 判断字符串是否为数字（纯数字）
     *
     * @param str 输入字符串
     * @return 是否为数字
     *
     * @example
     * <pre>{@code
     * boolean result = StringKit.isNumeric("123"); // true
     * boolean result2 = StringKit.isNumeric("12a3"); // false
     * }</pre>
     */
    public static boolean isNumeric(String str) {
        if (str == null || str.trim().isEmpty()) {
            return false;
        }
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断字符串是否为数字（支持负数和小数）
     *
     * @param str 输入字符串
     * @return 是否为数字
     *
     * @example
     * <pre>{@code
     * boolean result = StringKit.isNumericExtended("-123.45"); // true
     * boolean result2 = StringKit.isNumericExtended("12.3.4"); // false
     * }</pre>
     */
    public static boolean isNumericExtended(String str) {
        if (str == null || str.trim().isEmpty()) {
            return false;
        }
        boolean hasDecimalPoint = false;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (i == 0 && c == '-') {
                continue; // 允许负号开头
            }
            if (c == '.' && !hasDecimalPoint) {
                hasDecimalPoint = true;
                continue; // 允许一个小数点
            }
            if (!Character.isDigit(c)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 验证字符串长度范围
     *
     * @param str 待验证字符串
     * @param minLength 最小长度
     * @param maxLength 最大长度
     * @return boolean 长度在范围内返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * if (StringKit.isValidLength(password, 6, 20)) {
     *     // 验证通过
     * }
     * }</pre>
     */
    public static boolean isValidLength(String str, int minLength, int maxLength) {
        if (StrKit.isBlank(str)) {
            return false;
        }
        return str.length() >= minLength && str.length() <= maxLength;
    }

    /**
     * 验证多个字符串是否全部有效
     *
     * @param strings 待验证字符串数组
     * @return boolean 所有字符串都有效返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * if (StringKit.validateStrings(username, password, email)) {
     *     // 所有参数都有效
     * }
     * }</pre>
     */
    public static boolean validateStrings(String... strings) {
        for (String str : strings) {
            if (isNullOrInvalid(str)) {
                return false;
            }
        }
        return true;
    }

    // ========== 字符串处理方法 ==========

    /**
     * 截断字符串，如果超过指定长度则添加省略号
     *
     * @param str 输入字符串
     * @param maxLength 最大长度
     * @return 截断后的字符串
     *
     * @example
     * <pre>{@code
     * String result = StringKit.truncate("这是一个很长的字符串", 5);
     * // 返回 "这是一个..."
     * }</pre>
     */
    public static String truncate(String str, int maxLength) {
        if (StrKit.isBlank(str) || str.length() <= maxLength) {
            return str;
        }

        return str.substring(0, maxLength) + "...";
    }

    /**
     * 按字节长度截取字符串（考虑中文字符）
     *
     * @param str 输入字符串
     * @param length 字节长度
     * @return 截取后的字符串
     *
     * @example
     * <pre>{@code
     * String result = StringKit.substring("Hello世界", 7);
     * // 返回 "Hello世..."
     * }</pre>
     */
    public static String substring(String str, int length) {
        if (StrKit.isBlank(str) || str.length() < length / 2) {
            return str;
        }

        int count = 0;
        StringBuilder sb = new StringBuilder();
        String[] ss = str.split("");
        for (int i = 0; i < ss.length; i++) {
            count += ss[i].getBytes().length > 1 ? 2 : 1;
            sb.append(ss[i]);
            if (count >= length) {
                break;
            }
        }
        // 不需要显示...的可以直接return sb.toString();
        return (sb.toString().length() < str.length()) ? sb.append("...").toString() : str;
    }

    /**
     * 移除HTML标签
     *
     * @param html 包含HTML的字符串
     * @return 纯文本
     *
     * @example
     * <pre>{@code
     * String result = StringKit.stripHtml("<p>Hello</p>");
     * // 返回 "Hello"
     * }</pre>
     */
    public static String stripHtml(String html) {
        if (StrKit.isBlank(html)) {
            return html;
        }

        return html.replaceAll("<[^>]+>", "");
    }

    /**
     * 隐藏敏感信息
     *
     * @param str 原始字符串
     * @param start 开头保留字符数
     * @param end 结尾保留字符数
     * @return String 隐藏后的字符串
     *
     * @example
     * <pre>{@code
     * String hiddenPhone = StringKit.hideSensitiveInfo("13812345678", 3, 4);
     * // 返回 "138****5678"
     * }</pre>
     */
    public static String hideSensitiveInfo(String str, int start, int end) {
        if (StrKit.isBlank(str) || str.length() <= start + end) {
            return "***";
        }
        String startStr = str.substring(0, start);
        String endStr = str.substring(str.length() - end);
        return startStr + "***" + endStr;
    }

    /**
     * 生成驼峰命名（首字母小写）
     *
     * @param str 输入字符串
     * @return 驼峰命名字符串
     *
     * @example
     * <pre>{@code
     * String result = StringKit.toCamelCase("hello_world");
     * // 返回 "helloWorld"
     * }</pre>
     */
    public static String toCamelCase(String str) {
        if (StrKit.isBlank(str)) {
            return str;
        }

        String[] parts = str.split("[_\\-\\s]");
        StringBuilder result = new StringBuilder(parts[0].toLowerCase());

        for (int i = 1; i < parts.length; i++) {
            if (!parts[i].isEmpty()) {
                result.append(parts[i].substring(0, 1).toUpperCase())
                        .append(parts[i].substring(1).toLowerCase());
            }
        }

        return result.toString();
    }

    /**
     * 生成帕斯卡命名（首字母大写）
     *
     * @param str 输入字符串
     * @return 帕斯卡命名字符串
     *
     * @example
     * <pre>{@code
     * String result = StringKit.toPascalCase("hello_world");
     * // 返回 "HelloWorld"
     * }</pre>
     */
    public static String toPascalCase(String str) {
        String camelCase = toCamelCase(str);
        if (StrKit.isBlank(camelCase)) {
            return camelCase;
        }
        return camelCase.substring(0, 1).toUpperCase() + camelCase.substring(1);
    }

    // ========== 编码解码方法 ==========

    /**
     * URL解码
     *
     * @param str 编码后的字符串
     * @return 解码后的字符串
     *
     * @example
     * <pre>{@code
     * String result = StringKit.urldecode("Hello%20World");
     * // 返回 "Hello World"
     * }</pre>
     */
    public static String urldecode(String str) {
        if (str == null) return "";
        try {
            return URLDecoder.decode(str, "utf-8");
        } catch (Exception e) {
            return str;
        }
    }

    /**
     * URL编码
     *
     * @param str 原始字符串
     * @return 编码后的字符串
     *
     * @example
     * <pre>{@code
     * String result = StringKit.urlencode("Hello World");
     * // 返回 "Hello%20World"
     * }</pre>
     */
    public static String urlencode(String str) {
        if (str == null) return "";
        try {
            return URLEncoder.encode(str, "UTF-8");
        } catch (Exception e) {
            return str;
        }
    }

    // ========== 随机字符串生成 ==========

    /**
     * 生成随机字符串
     *
     * @param length 字符串长度
     * @return 随机字符串
     *
     * @example
     * <pre>{@code
     * String random = StringKit.randomString(10);
     * // 返回 "aB3xY8pQ2r"
     * }</pre>
     */
    public static String randomString(int length) {
        if (length <= 0) {
            return "";
        }

        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder(length);
        Random random = new Random();

        for (int i = 0; i < length; i++) {
            int index = random.nextInt(chars.length());
            sb.append(chars.charAt(index));
        }

        return sb.toString();
    }

    /**
     * 生成数字验证码
     *
     * @param length 验证码长度
     * @return String 数字验证码
     *
     * @example
     * <pre>{@code
     * String smsCode = StringKit.generateNumericCode(6);
     * // 返回 "123456"
     * }</pre>
     */
    public static String generateNumericCode(int length) {
        if (length <= 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }

    // ========== 通用验证方法 ==========

    /**
     * 验证对象是否为空或无效
     *
     * @param obj 待验证对象
     * @return boolean 对象为空或无效返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * if (StringKit.isNullOrInvalid(user)) {
     *     return "用户不存在";
     * }
     * }</pre>
     */
    public static boolean isNullOrInvalid(Object obj) {
        if (obj == null) {
            return true;
        }
        if (obj instanceof String) {
            return StrKit.isBlank((String) obj);
        }
        if (obj instanceof Number) {
            return ((Number) obj).doubleValue() <= 0;
        }
        if (obj instanceof Collection) {
            return ((Collection<?>) obj).isEmpty();
        }
        if (obj instanceof Map) {
            return ((Map<?, ?>) obj).isEmpty();
        }
        if (obj instanceof Object[]) {
            return ((Object[]) obj).length == 0;
        }
        return false;
    }

    /**
     * 检查字符串是否以指定前缀开头（忽略大小写）
     *
     * @param str 字符串
     * @param prefix 前缀
     * @return 是否以指定前缀开头
     *
     * @example
     * <pre>{@code
     * boolean result = StringKit.startsWithIgnoreCase("Hello", "HE");
     * // 返回 true
     * }</pre>
     */
    public static boolean startsWithIgnoreCase(String str, String prefix) {
        if (str == null || prefix == null) {
            return false;
        }
        return str.regionMatches(true, 0, prefix, 0, prefix.length());
    }

    /**
     * 检查字符串是否以指定后缀结尾（忽略大小写）
     *
     * @param str 字符串
     * @param suffix 后缀
     * @return 是否以指定后缀结尾
     *
     * @example
     * <pre>{@code
     * boolean result = StringKit.endsWithIgnoreCase("Hello", "LO");
     * // 返回 true
     * }</pre>
     */
    public static boolean endsWithIgnoreCase(String str, String suffix) {
        if (str == null || suffix == null) {
            return false;
        }
        int suffixLength = suffix.length();
        return str.regionMatches(true, str.length() - suffixLength, suffix, 0, suffixLength);
    }

    /**
     * 重复字符串指定次数
     *
     * @param str 字符串
     * @param times 重复次数
     * @return 重复后的字符串
     *
     * @example
     * <pre>{@code
     * String result = StringKit.repeat("ab", 3);
     * // 返回 "ababab"
     * }</pre>
     */
    public static String repeat(String str, int times) {
        if (str == null || times <= 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < times; i++) {
            sb.append(str);
        }
        return sb.toString();
    }
}